<script setup>
// import HelloWorld from './components/HelloWorld.vue'
// 一个单元格宽度190
import { ref, onMounted, defineAsyncComponent, shallowRef, computed, nextTick, reactive } from "vue";
// import Comp1  from "./components/comp1.vue";

//加载待选组件列表
import { compList } from "./data.json"


import { useStore } from 'vuex'
const buffer = ref(null);
const dragContainer = ref(null)
const baseWidth = 190;
const baseHeight = 131.6;
const DragLeft = ref(null)
const DragRight = ref(null)
const currentProp = ref({})
const layout = ref([]);
const layout2 = ref([]);

const gridlayout = ref(null)
const gridlayout2 = ref(null)
const itemref = ref(null)
const itemref2 = ref(null)

const myHtml = ref('')
const isShow = ref(false)
// 存放实际的dom元素
const target = ref({})
const colNum = 16
const tempRef = ref(null);

const isDrag = ref(true);

// const bufferList = reactive([])

// 两个目标区域 指示当前拖动到那个目标区域中
const area = ref('')


// 添加编辑和保存的模式
const isEdit = ref(false)

const store = useStore()
const locations = ref([])


// 拿到图片文件路径
onMounted(() => {
  // document.addEventListener("dragover", function (e) {
  //   mouseXY.value.x = e.clientX;
  //   mouseXY.value.y = e.clientY;
  // }, false);


  // 恢复数据
  if (store.state.layout) {
    // layout.value = store.state.layout
    locations.value = store.state.layout

  }
  // 异步加载组件
  // bufferList.push

  // bufferList.push(...layout.value.map(
  //   item=>{
  //     const comp = defineAsyncComponent(() => import(item.compValue))
  //     return {
  //       id:item.i,
  //       comp:comp
  //     }

  //   }
  // ) )
})

let mouseXY = ref({
  x: null,
  y: null
})
let DragPos = ref({ "x": null, "y": null, "w": 1, "h": 1, "i": null })
const drag = (e) => {
  // isDrag.value = false

  let parentRect = DragLeft.value.getBoundingClientRect();
  let mouseInGrid = false;
  // let parentRect2 = DragRight.value.getBoundingClientRect();
  // console.log(parentRect, 'kkk')
  if (((mouseXY.value.x > parentRect.left) && (mouseXY.value.x < parentRect.right)) && ((mouseXY.value.y > parentRect.top) && (mouseXY.value.y < parentRect.bottom))) {
    area.value = 'left'
    mouseInGrid = true;

  }
  // else if (((mouseXY.value.x > parentRect2.left) && (mouseXY.value.x < parentRect2.right)) && ((mouseXY.value.y > parentRect2.top) && (mouseXY.value.y < parentRect2.bottom))) {
  //   area.value = 'right'
  //   mouseInGrid = true;

  // }


  // 如果当前的元素被拖动到目标区域中
  // 如果当前的元素不在layout当中 就将他push 进去
  // 左边添加
  if (mouseInGrid === true && (area.value === 'left') && (layout.value.findIndex(item => item.i === 'drop')) === -1) {
    // 计算w和h

    let h = currentProp.value.lins * baseHeight / 65.8;
    let w = currentProp.value.cols * baseWidth / 95;
    // (layout.value.length * 2) % (colNum)
    // layout.value.length + (colNum)
    layout.value.push({
      x: (layout.value.length * 2) % (colNum),
      y: layout.value.length, // puts it at the bottom
      w,
      h,
      i: 'drop',
      id: currentProp.value.id
    });

  }
  // if (mouseInGrid === true && (area.value === 'right') && (layout2.value.findIndex(item => item.i === 'drop2')) === -1) {
  //   // 计算w和h

  //   let h = currentProp.value.lins * baseHeight / 65.8;
  //   let w = currentProp.value.cols * baseWidth / 95;
  //   // (layout.value.length * 2) % (colNum)
  //   // layout.value.length + (colNum)
  //   layout2.value.push({
  //     x: (layout.value.length * 2) % (colNum),
  //     y: layout.value.length, // puts it at the bottom
  //     w,
  //     h,
  //     i: 'drop2',
  //     id: currentProp.value.id,
  //   });

  // }
 

  let index;
  if (area.value === 'left') {
    index = layout.value.findIndex(item => item.i === 'drop');
  }
  // else if (area.value === 'right') {
  //   index = layout2.value.findIndex(item => item.i === 'drop2');

  // }
  if (index !== -1) {
    // if (area.value === 'left') {
    //   try {
    //     gridlayout.value.$refs.item.children[layout.value.length].style.display = 'none'
    //   } catch { }

    // }

    // 拖进去之后这个值就不等于-1
    // dragContainer.value.dragging =  {"top": mouseXY.value.y - parentRect.top, "left": mouseXY.value.x - parentRect.left};
    // console.log(  dragContainer.value.calcXY)
    // console.log(gridlayout.value.$refs.item.children[0])
    // const el = gridlayout.value.$refs.item.children[index];
    // el.dragging =  {"top": mouseXY.value.y - parentRect.top, "left": mouseXY.value.x - parentRect.left};
    // let new_pos = el.calcXY(top,left) = el.calcXY(mouseXY.value.y - parentRect.top, mouseXY.value.x - parentRect.left);


    // 区分左右
    if (area.value === 'left') {

      const el = itemref.value[index];
      if (!el) {
        return
      }
      el.dragging = {
        top: mouseXY.value.y - parentRect.top,
        left: mouseXY.value.x - parentRect.left
      }
      const new_pos = el.calcXY(mouseXY.value.y - parentRect.top, mouseXY.value.x - parentRect.left)

      // const relx =parseInt((mouseXY.value.x - parentRect.left) / 95);
      // const rely =parseInt((mouseXY.value.y - parentRect.top) / 65.8)
      let h = currentProp.value.lins * baseHeight / 65.8;
      let w = currentProp.value.cols * baseWidth / 95;
      if (mouseInGrid === true) {
        // gridlayout.value.dragEvent('dragstart', currentProp.value.id,3, 4, 1, 1)
        // 手动算x

        gridlayout.value.dragEvent('dragstart', 'drop', new_pos.x, new_pos.y, h, w)
        DragPos.value.i = currentProp.value.id;
        DragPos.value.x = layout.value[index].x;
        DragPos.value.y = layout.value[index].y;
        DragPos.value.h = h;
        DragPos.value.w = w;

        // console.log(mouseXY.value.y - parentRect.top, mouseXY.value.x - parentRect.left,'实时位置')
      }
      if (mouseInGrid === false) {
        gridlayout.value.dragEvent('dragend', 'drop', new_pos.x, new_pos.y, h, w);
        layout.value = layout.value.filter(obj => obj.i !== 'drop');
        area.value = ''

      }
    }
    // if (area.value === 'right') {
    //   // console.log()
    //   const el = itemref2.value[index];
    //   if (!el) {
    //     return
    //   }
    //   el.dragging = {
    //     top: mouseXY.value.y - parentRect2.top,
    //     left: mouseXY.value.x - parentRect2.left
    //   }
    //   const new_pos = el.calcXY(mouseXY.value.y - parentRect2.top, mouseXY.value.x - parentRect2.left)
    //   console.log(new_pos, 'kky')

    //   // const relx =parseInt((mouseXY.value.x - parentRect2.left) / 95);
    //   // const rely = parseInt((mouseXY.value.y - parentRect2.top) / 65.8)
    //   let h = currentProp.value.lins * baseHeight / 65.8;
    //   let w = currentProp.value.cols * baseWidth / 95;
    //   if (mouseInGrid === true) {
    //     // gridlayout.value.dragEvent('dragstart', currentProp.value.id,3, 4, 1, 1)
    //     // 手动算x
    //     gridlayout2.value.dragEvent('dragstart', 'drop2', new_pos.x, new_pos.y, h, w)
    //     DragPos.value.i = currentProp.value.id;
    //     DragPos.value.x = layout2.value[index].x;
    //     DragPos.value.y = layout2.value[index].y;
    //     DragPos.value.h = h;
    //     DragPos.value.w = w;

    //     // console.log(DragPos,';;;')
    //     // console.log(mouseXY.value.y - parentRect.top, mouseXY.value.x - parentRect.left,'实时位置')
    //   }
    //   if (mouseInGrid === false) {
    //     gridlayout2.value.dragEvent('dragend', 'drop2', new_pos.x, new_pos.y, h, w);
    //     layout2.value = layout2.value.filter(obj => obj.i !== 'drop2');
    //     area.value = ''
    //   }
    // }

  }

}

const getRandomKey = () => {
  return Math.random().toString(16).substring(2, 8)
}
const addNew = (lins, cols) => {

  // 清空当前缓冲区的元素
  dragContainer.value.innerHTML = ''
  // 在缓冲区中生成一个待添加的元素
  target.value = document.createElement('div');
  target.value.style.height = lins * baseHeight + 'px';
  target.value.style.width = cols * baseWidth + 'px';
  target.value.style.backgroundColor = 'rgb(67,198,249)';
  target.value.innerHTML = `${lins} x ${cols}`
  target.value.className = 'new-box'
  dragContainer.value.appendChild(target.value);
  // 为新元素创建一个对象 包括size和id
  // console.log()
  const id = getRandomKey()
  currentProp.value = {
    id,
    lins,
    cols
  }
}

const dragend = () => {
  let parentRect = DragLeft.value.getBoundingClientRect();
  // let parentRect2 = DragRight.value.getBoundingClientRect();

  let mouseInGrid = false;
  if (((mouseXY.value.x > parentRect.left) && (mouseXY.value.x < parentRect.right)) && ((mouseXY.value.y > parentRect.top) && (mouseXY.value.y < parentRect.bottom))) {
    mouseInGrid = true;
    area.value = 'left'


  }
  // if (((mouseXY.value.x > parentRect2.left) && (mouseXY.value.x < parentRect2.right)) && ((mouseXY.value.y > parentRect2.top) && (mouseXY.value.y < parentRect2.bottom))) {
  //   mouseInGrid = true;
  //   area.value = 'right'

  // }
  if (mouseInGrid === true) {
    // 分别判断左右
    if (area.value === 'left') {
      gridlayout.value.dragEvent('dragend', 'drop', DragPos.value.x, DragPos.value.x, DragPos.value.h, DragPos.value.w);
      layout.value = layout.value.filter(obj => obj.i !== 'drop');
      // 拿到id判断是否能添加
      // 拿到height 和top 

      // const place = document.querySelector('.vue-grid-placeholder').style
      // const pHeight = place.height
      // const pTop = place.transform.split(',')[1];
      // console.log(pHeight,pTop)


      gridlayout.value.dragEvent('dragend', DragPos.value.i, DragPos.value.x, DragPos.value.y, DragPos.value.h, DragPos.value.w);

      const place = DragLeft.value.querySelector('.vue-grid-placeholder').style;
      const pHeight = place.height
      const pTop = place.transform.split(',')[1];
      // console.log(pHeight, pTop)
      if (parseInt(pHeight) + parseInt(pTop) <= 390) {
        layout.value.push({
          x: DragPos.value.x,
          y: DragPos.value.y,
          w: DragPos.value.w,
          h: DragPos.value.h,
          i: DragPos.value.i,
          compValue: currentProp.value.path,
          info: 'new',
          loc: 'left'
        });
        // 找到目标元素
        nextTick(() => {
          const cur = document.getElementById(DragPos.value.i)
          // console.log(cur)
          cur.style.transform = place.transform;
        })
      }



      // console.log(pHeight,pTop)
      // const cur = document.getElementById(DragPos.value.i).style
      // const y = cur.transform.split(',')[1]
      // const yHeight = cur.height;
      // console.log(yHeight)
      // console.log(parseInt(y), '111')
      // console.log(parseInt(yHeight) + parseInt(y), '111')

      // if (parseInt(yHeight) + parseInt(y) > 390) {
      //   layout.value = layout.value.filter(obj => obj.i !== DragPos.value.i);
      // }




      // console.log(layout, '数据')
    }
    // if (area.value === 'right') {
    //   gridlayout2.value.dragEvent('dragend', 'drop2', DragPos.value.x, DragPos.value.x, DragPos.value.h, DragPos.value.w);
    //   layout2.value = layout2.value.filter(obj => obj.i !== 'drop2');
    //   gridlayout2.value.dragEvent('dragend', DragPos.value.i, DragPos.value.x, DragPos.value.y, DragPos.value.h, DragPos.value.w);

    //   const place = DragRight.value.querySelector('.vue-grid-placeholder').style;
    //   const pHeight = place.height
    //   const pTop = place.transform.split(',')[1];
    //   console.log(pHeight, pTop)
    //   if (parseInt(pHeight) + parseInt(pTop) <= 390) {
    //     layout2.value.push({
    //       x: DragPos.value.x,
    //       y: DragPos.value.y,
    //       w: DragPos.value.w,
    //       h: DragPos.value.h,
    //       i: DragPos.value.i,
    //       compValue: currentProp.value.path,
    //       info: 'new',
    //       loc: 'right'
    //     });
    //     // 找到目标元素
    //     nextTick(() => {
    //       const cur = document.getElementById(DragPos.value.i)
    //       console.log(cur)
    //       cur.style.transform = place.transform;

    //     })
    //   }

    //   // layout2.value.push({
    //   //   x: DragPos.value.x,
    //   //   y: DragPos.value.y,
    //   //   w: DragPos.value.w,
    //   //   h: DragPos.value.h,
    //   //   i: DragPos.value.i,
    //   //   compValue: currentProp.value.path,
    //   //   info: 'new',
    //   //   loc: 'right'

    //   // });


    // }

    //销毁页面上的元素
    compRef.value = {};
    compShow.value = false;
    area.value = ''

    // isDrag.value = true

    // console.log(layout.value)

    //  gridlayout.value.$refs.item.children[DragPos.value.i].appendChild( target.value) 
    // const tar = document.querySelector(`#item${DragPos.value.i}`);
    // console.log( tar)
    // tar.innerHTML = target.value;
    // isShow.value = true

  }
}


const compRef = shallowRef({});
const compShow = ref(false)
const addComp = (lins, cols, item) => {
  // console.log('新增组件',lins,cols,item)

  // compShow.value = true
  // compRef.value = defineAsyncComponent(() => import(item.path));
  const id = getRandomKey()
  // currentProp.value = {
  //   id,
  //   lins,
  //   cols,
  //   path: item.path
  // }
  layout.value.push(
    {
      i: id,
      x: 7,
      y: 2,
      h: lins * baseHeight / 65.8,
      w: cols * baseWidth / 95,
      compValue: item.path,
      info: 'new',
      loc: 'left',
      // comp:defineAsyncComponent(() => import(item.path))
      imgPath: item.imgPath,
      name: item.name

    }
  )
  // console.log(layout.value, 'll')

}


const removeItem = (val) => {

  layout.value = layout.value.filter(item => item.i !== val.i);

  // 将项目还原到容器中
  // compShow.value = true;
  // compRef.value = defineAsyncComponent(() => import(val.compValue));
}

const handleSave = () => {
  if (isEdit.value) {
    // 保存当前页面内容
    isEdit.value = false
    // 保存layout

    // 找到每个项目的位置
    const loclist = layout.value.filter(item => {
      return ((item.x + item.w <= 4) && (item.y + item.h <= 6)) || (item.x >= 12 && item.y + item.h <= 6)
    }).map(item => {
      const tar = document.getElementById(item.i).style;
      // 需要对位置做修正
      return {
        compValue: item.compValue,
        h: item.h,
        i: item.i,
        info: item.info,
        moved: item.moved,
        w: item.w,
        x: item.x,
        y: item.y,
        transform: tar.transform,
        imgPath: item.imgPath,
        name: item.name
      }
    })
    // console.log(loclist, '过滤的数组')
    //location中有拿到的组件地址
    // 根据id 找到过滤数组的transform
    locations.value = loclist
    // store.commit('saveLayout', layout.value);
    // 将当前loclist 存入本地
    store.commit('saveLayout', loclist);

  }
  else {
    // 进入编辑模式
    isEdit.value = true
    // console.log(locations.value)
    layout.value = locations.value.map(item => {
      return {
        ...item,
        imgPath: item.imgPath

      }
    })

  }
}
const showCompModeList = computed(() => {
  if (isEdit.value) {
    return []
  } else {
    // 非编辑模式需要把目标渲染出来
    return locations.value.map(item => {
      return {
        ...item,
        comval: defineAsyncComponent(() => import(`@/components/${item.name}.vue`))
      }
    })
  }
})

const handleMapClick = () => {
  alert('地图层级事件触发')
}

const getImg = (url) => {
  return new URL(url, import.meta.url).href

}
</script>

<template>
  <div class="demo-wrap">
    <div class="demo-content">
      <div class="demo-title">
        <!-- <div class="demo-btn" @click="addComp(1, 1)">
          点击新增组件
        </div> -->
        <div class="demo-btn posi" @click="handleSave">
          {{ isEdit ? '保存' : '编辑' }}
        </div>
        <template v-if="isEdit">
          <div v-for="item in compList" class="demo-btn" :key="item.path" @click="addComp(item.lins, item.cols, item)">
            新增{{ item.lins }} * {{ item.cols }}组件
          </div>
        </template>


      </div>
      <div class="demo-main">
        <div class="demo-left" ref="DragLeft">
          <grid-layout v-if="isEdit" ref="gridlayout" class="num" :auto-size="false" :layout.sync="layout" :col-num="16"
            :row-num="6" :margin="[0, 0]" :colWidth="95" :maxRows="6" :rowHeight="65" :responsive="false"
            :preventCollision="true" :is-draggable="true" :is-resizable="false" :use-css-transforms="true"
            :verticalCompact="false">
            <grid-item ref="itemref" :key="item.i" :id="item.i" v-for="(item, index) in layout" :x="item.x" :y="item.y"
              :w="item.w" :h="item.h" :i="item.i">
              <!-- <span class="text">{{ item.i }}</span> -->
              <!-- <div :id="`item${index}`" ref="tempRef"></div> -->
              <!-- <component :is="item.comp" v-if="item.info ">
                <div>{{ item.i }}</div>
              </component> -->
              <!-- <img :src="item.imgPath"   alt=""> -->
              <img :src="item.imgPath" alt="">

              <div class="img-indecator">
                组件快照 组件id:{{ item.i }}
              </div>
              <span class="remove" @click="removeItem(item)">x</span>
            </grid-item>
          </grid-layout>
          <div class="all-container" v-if="!isEdit">
            <div class="map-container">
              <div class="demo-btn map-btn" @click="handleMapClick">我是一个地图的按钮 </div>
            </div>
            <!-- 组件直接相对于这个容器进行定位 -->
            <div class="zIndex" v-for="it in showCompModeList"
              :style="{ zIndex: 666, transform: `translate(5px,10px)` }">
              <div :key="it.i" :style="{ zIndex: 777, transform: it.transform }">
                <component :is="it.comval"></component>

              </div>
            </div>

          </div>

        </div>
        <!-- <div class="demo-middle" ref="buffer">
          <div class="drag-container" @drag="drag" ref="dragContainer" draggable="true" @dragend="dragend">
            <component :is="compRef" v-if="compShow"></component>
          </div>
        </div> -->
        <!-- <div class="demo-right" ref="DragRight">
          <grid-layout ref="gridlayout2" class="num" :auto-size="false" :layout="total2" :col-num="4" :row-num="6"
            :margin="[0, 0]" :colWidth="95" :maxRows="6" :rowHeight="65" :responsive="false" :preventCollision="true"
            :is-draggable="true" :is-resizable="false" :use-css-transforms="true">
            <grid-item ref="itemref2" :key="item.i" :id="item.i" v-for="(item, index) in total2" :x="item.x" :y="item.y"
              :w="item.w" :h="item.h" :i="item.i">
              
              <component :is="item.comp" v-if="item.info && item.loc === 'right'"></component>

            </grid-item>
          </grid-layout>
        </div> -->

      </div>
    </div>
  </div>



</template>

<style>
.demo-wrap {
  height: 100%;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.num {
  overflow: hidden;
  height: 390px !important;
}

.demo-content {
  height: 450px;
  width: 1600px;
  background-color: rgb(224, 219, 238);

}

.demo-main {
  /* display: flex; */
  position: relative;
  width: 1600px;
  height: 403px;

}

.demo-title {
  text-align: right;
  width: 100%;
  height: 47px;
  background-color: rgb(244, 208, 212);
  position: relative;
}

.demo-left {
  padding: 10px 5px;
  box-sizing: border-box;
  /* width: 400px;
  height: 407px; */
  background-color: rgba(255, 255, 255, 0.3);
  width: 100%;
  position: relative;
  width: 1600px;
  height: 403px;

}

.all-container {
  height: 390px;
  width: 1590px;
  position: absolute;
  left: 0px;
  top: 0px;

  z-index: 10
}

.map-container {
  height: 390px;
  width: 1590px;
  position: absolute;
  left: 0px;
  top: 0px;
  text-align: center;
  z-index: -8;
}

.zIndex {
  z-index: 888;
}

.comp-container {
  height: 390px;
  width: 1590px;
  position: absolute;
  left: 0px;
  top: 0px;

  z-index: 99
}

.demo-right {
  padding: 10px 5px;
  box-sizing: border-box;

  width: 400px;
  height: 407px;
  background-color: rgba(255, 255, 255, 0.3);
  flex: 0 0 auto;

}

.demo-middle {
  box-sizing: border-box;
  flex: 1 1 auto;
  position: absolute;
  left: 50%;
  top: 50px;
  transform: translate(-50%, -50%);

}

.demo-btn {
  height: 30px;
  background-color: rgb(27, 160, 53);
  display: inline-block;
  color: #fff;
  padding: 0 10px;
  line-height: 30px;
  border-radius: 5px;
  font-size: 13px;
  margin: 0 5px;


}

.new-box {
  font-size: 1.2em;
  color: red;
  display: flex;
  justify-content: center;
  align-items: center;
}

.drag-container {
  display: inline-block;
}

.remove {
  position: absolute;
  right: 15px;
  top: 5px;
  cursor: pointer;
  z-index: 999;
}

.img-indecator {
  position: absolute;
  top: 5px;
  z-index: 888;
  color: #fff;
  left: 5px
}

.posi {
  position: absolute;
  left: 10px;
  top: 5px;
}

.test-bottom {
  position: absolute;
  left: 0px;
  top: 70%;
}

.map-btn {
  display: inline-block;

  margin: 300px auto;
}
</style>
